﻿using System;
using System.Collections.Generic;
using System.Text;
using SecureConnection.Utils;


namespace RemoteCode.Remote
{
    public class RemoteClass : IDisposable
    {
        internal RemoteClass(int id_, Nexum host_)
        {
            this.id = id_;
            this.host = host_;
            this.Disposed = false;
        }

        internal int id;
        public bool Disposed { get; private set; }
        internal Nexum host;
       

        public void Dispose()
        {
            if (Disposed)
                return;

            lock (host.RemoteClasses)
            {
                host.RemoteClasses.Remove(id);
            }

            ByteArrayWriter bw = new ByteArrayWriter();
            bw.WriteByte(0); //Normal Class
            bw.WriteInt(id);

            Disposed = true;
            id = 0;

            Result r = host.GetResult(ref bw, NexumId.DisposeClass);

            host = null;
        }

        public T InvokeMethod<T>(string methodName, params object[] parameters)
        {
            return (T)InvokeMethod(methodName, parameters);
        }
        public object InvokeMethod(string methodName, params object[] parameters)
        {
            if (Disposed)
                throw new Exception("Disposed");

            ByteArrayWriter bw = new ByteArrayWriter();

            bw.WriteByte(0); //Normal Class
            bw.WriteByte(0); //NoPointer
            bw.WriteInt(id);
            bw.WriteString(methodName);
            SerializationHelper.SerializeArray(parameters, ref bw);

            Result r = host.GetResult(ref bw, NexumId.Invoke);

            return r.ret;
        }
        public void InvokeMethod(string methodName, Nexum.Callback callback, object userstate, params object[] parameters)
        {
            if (Disposed)
                throw new Exception("Disposed");

            ByteArrayWriter bw = new ByteArrayWriter();

            bw.WriteByte(0); //Normal Class
            bw.WriteByte(0); //No Pointer
            bw.WriteInt(id);
            bw.WriteString(methodName);
            SerializationHelper.SerializeArray(parameters, ref bw);

            host.GetResult_Callback(ref bw, NexumId.Invoke, callback, userstate);
        }
        public RemoteClass InvokeMethod_Pointer(string methodName, params object[] parameters)
        {
            if (Disposed)
                throw new Exception("Disposed");

            ByteArrayWriter bw = new ByteArrayWriter();

            bw.WriteByte(0); //Normal Class
            bw.WriteByte(1); //Pointer
            bw.WriteInt(id);
            bw.WriteString(methodName);
            SerializationHelper.SerializeArray(parameters, ref bw);

            Result r = host.GetResult(ref bw, NexumId.Invoke);

            lock (host.RemoteClasses)
            {
                host.RemoteClasses.Add((int)r.ret, new RemoteClass((int)r.ret, host));
                return host.RemoteClasses[(int)r.ret];
            }
        }
        public void InvokeMethod_Pointer(string methodName, Nexum.Callback callback, object userstate, params object[] parameters)
        {
            if (Disposed)
                throw new Exception("Disposed");

            ByteArrayWriter bw = new ByteArrayWriter();

            bw.WriteByte(0); //Normal Class
            bw.WriteByte(1); //Pointer
            bw.WriteInt(id);
            bw.WriteString(methodName);
            SerializationHelper.SerializeArray(parameters, ref bw);

            host.GetResult_Callback(ref bw, NexumId.Invoke, callback, userstate);
        }
        public void InvokeMethod_NoSync(string methodName, params object[] parameters)
        {
            if (Disposed)
                throw new Exception("Disposed");

            ByteArrayWriter bw = new ByteArrayWriter();

            bw.WriteByte(0); //Normal Class
            bw.WriteByte(0); //No Pointer
            bw.WriteInt(id);
            bw.WriteString(methodName);
            SerializationHelper.SerializeArray(parameters, ref bw);

            host.GetResult_NoSync(ref bw, NexumId.Invoke);
        }       
    }
}
